/**
 * 
 */
package cn.bigcontainer.alt.meta.service.impl;

import java.io.File;
import java.util.*;

import javax.annotation.Resource;

import cn.bigcontainer.alt.common.exception.BigException;
import cn.bigcontainer.alt.common.util.ExcelUtil;
import cn.bigcontainer.alt.common.util.WoKit;
import cn.bigcontainer.alt.meta.exception.MException;
import cn.bigcontainer.alt.meta.service.MFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bigcontainer.alt.common.entity.BigMap;
import cn.bigcontainer.alt.meta.dto.MAppDto;
import cn.bigcontainer.alt.meta.dto.MCrud;
import cn.bigcontainer.alt.meta.dto.MViewDto;
import cn.bigcontainer.alt.meta.mapper.MAppMapper;
import cn.bigcontainer.alt.meta.po.MApp;
import cn.bigcontainer.alt.meta.po.MViewProperty;
import cn.bigcontainer.alt.meta.service.MAppService;
import cn.bigcontainer.alt.meta.service.MCrudService;
import lombok.extern.slf4j.Slf4j;

/**
 * @author cailei
 * @date 2017年6月14日
 */
@Service
@Transactional(rollbackFor = { Exception.class })
@Primary
@Slf4j
public class MCrudServiceImpl implements MCrudService {

	@Autowired
	private MAppService woAppService;

	@Resource
	private MAppMapper appMapper;

	/**
	 * @param id
	 * @param req
	 * @return
	 */
	private MCrud getCrud(String id, Map<String, Object> req) {
		MApp app = appMapper.selectById(id);
		MCrud crud = new MCrud(app, new BigMap<String, Object>().bigPutAll(req));
		return crud;
	}

	/**
	 * @param appId
	 * @param req
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public MViewDto loadListData(String appId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MViewDto list = crud.getListView();
		MViewDto search = crud.getSearchView();
		MViewDto viewDto = crud.beforeLoadList(list, search);
		if (viewDto != null) {
			return viewDto;
		}
		woAppService.loadListData(list, search);
		crud.afterLoadList(list, search);
		return list;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see wos.commons.services.IWoViewService#loadCreateForm(java.lang.String,
	 * java.lang.String, java.util.Map)
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public MViewDto loadCreateForm(String appId, String keyVal, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MViewDto form = crud.getCreateView();
		MViewDto fnew = crud.beforeLoadCreateForm(form, keyVal);
		if (fnew != null) {
			return fnew;
		}
		woAppService.loadCreateForm(form, keyVal);
		crud.afterLoadCreateForm(form, keyVal);
		return form;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * wos.commons.services.IWoViewService#submitCreateForm(java.lang.String,
	 * java.util.Map)
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public MViewDto submitCreateForm(String appId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MViewDto form = crud.getCreateView();
		MViewDto fnew = crud.beforeSubmitCreateForm(form);
		if (fnew != null) {
			return fnew;
		}
		woAppService.submitCreateForm(form);
		crud.afterSubmitCreateForm(form);
		return form;
	}

	@Override
	@Transactional(rollbackFor = { Exception.class })
	public MViewDto loadUpdateForm(String appId, String keyVal, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MViewDto form = crud.getUpdateView();
		MViewDto fnew = crud.beforeLoadUpdateForm(form, keyVal);
		if (fnew != null) {
			return fnew;
		}
		woAppService.loadUpdateForm(form, keyVal);
		crud.afterLoadUpdateForm(form, keyVal);
		return form;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * wos.commons.services.IWoViewService#submitUpdateForm(java.lang.String,
	 * java.util.Map)
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public MViewDto submitUpdateForm(String appId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MViewDto form = crud.getUpdateView();
		MViewDto fnew = crud.beforeSubmitUpdateForm(form);
		if (fnew != null) {
			return fnew;
		}
		woAppService.submitUpdateForm(form);
		crud.afterSubmitUpdateForm(form);
		return form;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see wos.commons.services.IWoCrudService#loadCrud(java.lang.String,
	 * java.util.Map)
	 */
	@Override
	public MCrud loadCrud(String appId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		// woAppService.loadListData(crud.getListView(), crud.getSearchView());
		return crud;
	}

	@Override
	public MCrud loadCrudMeta(String appId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		return crud;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see wos.engine.services.IWoCrudService#deleteInstances(java.lang.String,
	 * java.lang.String, java.util.Map)
	 */
	@Override
	public void deleteObjects(String appId, String keyVals, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		MAppDto appDto = crud.delete(crud, keyVals);
		if (appDto == null) {
			woAppService.deleteObjects(crud.getObject(), keyVals);
		}
	}

	@Override
	public MViewProperty loadSelectorNameValues(String id, String propertyId, String propertyValue, Map<String, Object> req) {
		MApp app = appMapper.selectById(id);
		MAppDto crud = new MAppDto(app);
		MViewProperty viewProperty = crud.getViewProperty(propertyId);
		Object[] nameValues = viewProperty.getRelatedCrud().getObject().getNameValue(propertyValue);
		viewProperty.getData().put(MViewProperty.PARAM_NAME_VALUE, nameValues);
		return viewProperty;
	}

	@Override
	public Object[] loadSelectorNameValues(String id, String propertyValue) {
		if (WoKit.isEmpty(id)) {
			return loadSelectorNameValues(propertyValue);
		}
		MApp app = appMapper.selectById(id);
		MAppDto crud = new MAppDto(app);
		Object[] nameValues = crud.getObject().getNameValue(propertyValue);
		return nameValues;
	}

	@Resource
	private MFileService fileService;

	@Override
	public void importExcel(String appId, Integer fileId, Map<String, Object> req) {
		MCrud crud = getCrud(appId, req);
		File file = fileService.getFile(fileId);
		crud.importExcel(crud, ExcelUtil.getBook(file));
	}

	private Object[] loadSelectorNameValues(String propertyValues) {
		String[] values = propertyValues.split("[:,]");
		if (values.length % 2 == 1) {
			throw new MException(BigException.ERROR_FORMAT, propertyValues, "appId1:pkValue1,appId2:pkValue2,...");
		}
		List nameValues = new ArrayList();
		for (int i = 0; i < values.length; i += 2) {
			String id = values[i];
			String value = values[i + 1];
			MApp app = appMapper.selectById(id);
			MAppDto crud = new MAppDto(app);
			Object[] objects = crud.getObject().getNameValue(value);
			nameValues.add(objects[0]);
		}
		return nameValues.toArray();
	}
}
